 Assembler course part 3

 by Wanja Gayk

 Hi guys! The programs we've written so far aren't really all
 too useful, wouldn't you admit? But now we're going to try
 some cooler stuff. Today I want to show you how to produce a
 nice color effect on the screen ... Interested? Okay, start
 your monitors and let's get going!

 For starters we're going to let the first line of the screen
 change color. To be able to do that it's necessary to know
 how the C64 handles colors. This is how it works in the text
 mode: if you look at the screen memory you'll notice that
 the screen code for the character from the upper-left corner
 can be found in $0400 ... the next character to the right of
 it is in $0401 and the next chAracter to the right of that
 can be found in $0402, and so on. The first sign of the
 second line is in $0428 ($28 hex = 40 decimal), the one
 right of it in $0429 and so forth. The system's easy enough
 to understand, isn't it? You can find the screen codes for
 each of the characters in the C64 manual. I'd like to
 illustrate the whole thing on the screen with a simple
 Assembler program for which we need a new command:

 TXA / TAX and TYA / TAY

 TXA (Transfer X register to Accumulator), this command
 copies the value from the X register into the accumulator.
 To copy a value from the accumulator into the X register you
 have the command TAX (Transfer Accumulator to X register).
 These two commands are of course also available for the Y
 register, where they are called TYA (Transfer Y register to
 Accumulator) and TAY (Transfer Accumulator to Y register)
 respectively. The following program will show you their
 effects:

 .A 1000 LDX #$00

 .A 1002 TXA

 .A 1003 STA $0400, X

 .A 1006 INX

 .A 1007 BNE $1002

 .A 1009 RTS

 This program loads the values of $00 to $ff into the screen
 memory. It does a great job in demonstrating which value
 from the screen memory (screen code) is responsible for
 which sign. On some older C64's, you won't see anything with
 this code. The reason is that the older Kernal's internal
 CLR/Home routine does not fill color memory with the current
 cursor color, but instead, with the current BACKGROUND
 color. Any characters output without a specific color (e.g.
 by POKE or STA) are as invisible as an albino rabbit on a
 glacier (white on white). Just a few preparations will help
 solve the problem. Can you imagine which?

 This is how the program works: We start the X register at
 $00 and copy it into the accumulator. Now we load the
 content of the accumulator into the screen memory at $0400 +
 X. In the first run X is $00, so that the value of the
 accumulator (presently $00) is loaded into memory cell
 $0400. Now the X register is increased by one via the INX.
 As X does not equal zero, the BNE (Branch if Not Equal)
 instruction jumps back to $1002 where the value of the
 accumulator (now $01 thanks to the TXA instruction) is
 loaded into the screen memory. This process of copying X
 into the Accumulator and then storing to memory at $0400 + X
 continues until X = $ff. Again $ff is loaded into the screen
 memory at $04ff. The next command is INX, which tries to
 increase X once more. Since it has already reached $ff, the
 maximum value, X starts again at zero. Now that X has rolled
 over to Zero, the Zero-Flag is now set, and BNE does not
 jump anymore. The program proceeds to RTS and stops. RTS is
 a new command I'd like to explain briefly:

 RTS (ReTurn from Subroutine) - Normally subroutines are
 called up with SYS from BASIC or with JSR from Assembler.
 We're going to use JSR later on in this part of the course,
 where the command is going to be explained. Every time you
 call up a subroutine, the address to which it must return is
 stored on the processor stack. RTS takes these return
 addresses from the stack again and jumps back to them. RTS
 works comparable to RETURN in BASIC. In BASIC the command
 GOSUB 100 calls up a subroutine. RETURN then returns to the
 spot where the GOSUB command left off. So if you jump with
 SYS from BASIC to an Assembler program RTS will return from
 Assembler to BASIC.

 Well, now you've seen the elements the screen is composed of
 and know which screen codes represent which characters. But
 where are the colors I promised you so pretentiously? No
 problem whatsoever, since now we'll come to the color memory
 - also called color RAM. It starts at $d800 and is composed
 of the same elements as the screen memory. Each memory cell
 of the color RAM represents the color of one character found
 in the corresponding cell of the screen memory. The colors
 are treated similar to the border ($d020) and background
 ($d021) colors. Values from $00 up to $0f set the color of
 any one character. All values higher than these do not make
 sense as they only produce the same colors, i.e. $0a = light
 red, $1a = light red, $2a = light red, and so on. As you can
 see, only the second, low-order digit of the number - the
 so-called low-nybble (4-bits) - is important. You'll be best
 able to see that with the help of a little program with
 which we'll color the first line of the screen. First, let's
 set up a little color table:

 .M 1100 06 04 0e 0a 03 0f 0d 07

 .M 1108 01 01 07 0d 0f 03 0a 0e

 .M 1110 04 06 0b 0c 0f 01 0f 0c

 .M 1118 0b 09 02 08 0a 0f 07 01

 .M 1120 01 0d 03 05 0c 0b 0c 0f

 And now the program:

 .A 1000 LDX #$00

 .A 1002 STX S:D020

 .A 1005 STX $D021

 .A 1008 LDA $1100, X

 .A 100B STA $D800, X

 .A 100E INX

 .A 100F CPX #$28

 .A 1011 BNE $1008

 .A 1013 RTS

 What to do: just write anything you like in the first line
 of the screen in the BASIC editor, press SHIFT+RETURN (so
 the line will be ignored and you'll get no syntax error
 warning), start the program with SYS 4096 or from the
 monitor with G 1000, and you'll have a nicely colored first
 line.

 Now, how does this program work? Well by now you probably
 know, but here goes: First, we initialize X to $00, and
 store this zero value to the border and background color
 registers (convenient, isn't it?). Next, we start a loop, in
 which we first load a value from our table. The location
 pointer to will be $1100 + X, which will be $1100 since X is
 zero on the first run. The value is then stored to Color RAM
 at location $D800 + X, which will be $D800 on the first run,
 of course. X is then increased by 1 (INX) and compared
 against the value $28 (40 in decimal). If X is not equal to
 $28, the BNE instruction will cause a jump back to $1008. If
 they are not equal, the instruction fails and falls through
 to the RTS, where the program terminates.

 Each time the BNE branches back to $1008, X is increased by
 1 and a value is loaded from the table and stored to Color
 RAM. On the second pass through the loop, X will be 1, and
 so the byte copied will be from $1101 to $D801, followed by
 $1102 and $D802, and so on until X reaches $28.

 Okay, so now we have a colored first line, but it would be
 nice to have some motion, wouldn't it? So how are we going
 to do it? Let's start like this: let's take the first color
 value from our table and keep it in a temporary storage
 location. Then we move the whole table one position to the
 left. The second color value now takes the place of the
 first, the third that of the second and so on. The last
 value changes to the second last and leaves an empty space
 where we can deposit the value we have stored. Now let's
 bring the colors back onto the screen, which means copying
 the color table into the color RAM.

 In addition to the above routine we now need another one to
 be able to cycle the color table. And as it would be much
 too easy to store the first value if the table in the X or Y
 register, we'll use two new commands:

 PHA / PLA (PusH Accumulator, PulL Accumulator)

 PHA pushes the accumulator's content onto the processor
 stack in the same way that the processor pushes return
 addresses when executing a JSR or SYS command. PLA pulls the
 first value from the stack and transfers it to the
 accumulator.

 The stack is used to store jump addresses and other values.
 It works by the LIFO principle (Last In - First Out). That's
 to say if you push one byte directly after another onto the
 stack by use of the PHA and JSR instructions, the first PLA
 takes the byte that was most recently pushed, from the
 stack, and places it in the Accumulator. The second PLA
 pulls off the next most receltny puched byte. Since return
 addresses are also stored on the stack the number of bytes
 PULLed from within a subroutine or program must always equal
 that of those PUSHed within that same subroutine or program,
 otherwise you'll get a magnificent crash!

 But now let's look at a program that demonstrates the
 effects of the PHA and PLA commands. This program starts off
 at the address $1014 - directly following the other program.

 .A 1014 LDA $1100

 .A 1016 PHA

 .A 1017 LDX #$00

 .A 1019 LDA $1101, X

 .A 101C STA $1100, X

 .A 101F INX

 .A 1020 CPX #$27

 .A 1022 BNE $1019

 .A 1024 PLA

 .A 1025 STA $1127

 .A 1028 RTS

 What exactly is the effect of this little routine? It takes
 the first value from the table (at $1100) and pushes it onto
 the stack. Then it returns the X register value to $00,
 takes the second value (from $1101 + X) and puts it in the
 place of the first (to $1100 + X). X is increased by one and
 a check is made to see if X has already reached the number
 of table values (minus one, as the last one has been
 exchanged for the first one, so you don't need it anymore).
 If this is not the case, the loop is repeated. Otherwise,
 BNE will not jump and the program will continue at $1024
 where the byte last pushed onto the stack will be pulled off
 and put in the place of the last value of the table. Now
 we're finished - you've cycled through the table once. You
 only have to display it on the screen with the routine you
 wrote at $1000 (first program). Of course you could write a
 similar BASIC program looking like this:

 10 SYS 4096: SYS 4116: GOTO 10

 But this is an Assembler course, isn't it? So for testing
 purposes let's write a little routine at $1200 just to use
 it for demonstration. We're going to need one new command
 for it.

 JSR (Jump to SubRoutine)

 JSR jumps to a subroutine elsewhere in the computer's
 memory. JSR $1000, for example, would jump to the program
 that starts at memory cell $1000. The command has the same
 effect as GOSUB in BASIC - the equivalent of BASIC's RETURN
 command (to end a subroutine) is a simple RTS instruction in
 Assembler, as you already know. That's the reason why RTS
 jumps back to BASIC every time you call up the machine
 routine from BASIC with SYS. The command SYS is nothing but
 a JSR command disguised by the BASIC interpreter.

 But now let's finally come to the program. It doesn't return
 to BASIC because it doesn't have an RTS command at the end
 (it's an infinite loop, anyway):

 .A 1200 JSR $1000

 .A 1203 JSR $1014

 .A 1206 JMP $1200

 A really simple program: it jumps to the routine that
 displays the color table (JSR $1000) and then to the program
 that cycles the table ($1014). After that it jumps back to
 its own start where it branches again to the display
 routine, forming an infinite loop.

 You can easily start the effect on the screen with G1200 or
 in BASIC with SYS 4608 - to abort you've just got to press
 RUN / STOP-RESTORE - experts like you already know that of
 course. You'll see that things run nearly a little too fast
 (well, yes - there's nearly no stopping our dear little C64
 with Assembler programming). Therefore I'm going to show you
 in the next part how to synchronize the whole thing with the
 scanning beam that is responsible for the display. Then
 you'll get really close to the cool stuff: the INTERRUPT.
 Okay, stay hot for next time!
